use ::std::result::Result;
use std::{cell::RefCell, fmt};

use ::lrpar::NonStreamingLexer;
use lrlex::defaults::DefaultLexerTypes;
use lrpar::Span;
mod checkablelist;
mod list;
mod table;
mod text;
pub use checkablelist::*;
pub use list::*;
pub use table::*;
pub use text::*;
#[derive(Debug)]

pub enum Markdown<'input> {
    Heading {
        level: usize,
        content: TextList<'input>,
    },
    Text {
        content: TextList<'input>,
    },
    List {
        items: Vec<ListItem<'input>>,
        is_order: bool,
    },
    CheckableList {
        items: Vec<CheckableListItem<'input>>,
    },
    Table {
        heads: Row<'input>,
        rows: Vec<Row<'input>>,
        aligns: Vec<TableAlign>,
    },
    Error {
        info: String,
    },
    Code {
        content: &'input str,
    },
    Nul,
}
impl<'input> fmt::Display for Markdown<'input> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Markdown::Heading { level, content } => write!(f, "<h{level}>{content}</h>"),
            Markdown::Text { content } => write!(f, "<p>{}</p>", content),
            Markdown::List { items, is_order } => {
              let tag =   if *is_order {
                   "ol" 
                }else{
                    "ul"
                };
                write!(f, "<{tag}>")?;
                for ele in items.iter() {
                    write!(f, "{ele}")?;
                }
                write!(f, "</{tag}>")?;
                Ok(())
            }
            Markdown::Error { info } => writeln!(f, "Error:{info}"),
            Markdown::Code { content } => writeln!(f, "<code>\n{content}\n</code>"),
            Markdown::Nul => Ok(()),
            Markdown::Table {
                heads,
                rows,
                aligns: _,
            } => {
                write!(f, "<table><tr>")?;
                // for ele in aligns.iter() {
                //     write!(f, "{ele}")?;
                // }
                for ele in heads.cells.iter() {
                    write!(f, "<th>{ele}</th>")?;
                }
                write!(f, "</tr>")?;
                for ele in rows.iter() {
                    write!(f, "<tr>")?;
                    for ele in ele.cells.iter() {
                        write!(f, "<td>{ele}</td>")?;
                    }
                    write!(f, "</tr>")?;
                }
                write!(f, "</table>")?;
                Ok(())
            }
            Markdown::CheckableList { items } => {
                write!(f, "<dl>")?;
                for ele in items.iter() {
                    write!(f, "{ele}")?;
                }
                write!(f, "</dl>")?;
                Ok(())
            }
        }
    }
}
pub fn generate_markdown_list(items: Vec<ListItem<'_>>, is_order: bool) -> Markdown<'_> {
    Markdown::List { items, is_order }
}
pub fn generate_markdown_checkable_list(items: Vec<CheckableListItem<'_>>) -> Markdown<'_> {
    Markdown::CheckableList { items }
}
pub fn generate_head<'lexer, 'input: 'lexer>(
    lexer: &'lexer dyn NonStreamingLexer<'input, DefaultLexerTypes>,
    head: TextList<'input>,
    level: Span,
) -> Markdown<'input> {
    let level = lexer.span_str(level).trim().len();
    Markdown::Heading {
        level,
        content: head,
    }
}
pub fn generate_code<'lexer, 'input: 'lexer>(
    lexer: &'lexer dyn NonStreamingLexer<'input, DefaultLexerTypes>,
    code: Result<Span, ()>,
) -> Markdown<'input> {
    match code {
        Ok(code) => {
            let code = lexer.span_str(code);
            Markdown::Code { content: code }
        }
        Err(err) => Markdown::Error {
            info: format!("{:?}", err),
        },
    }
}
pub fn generate_list_item<'lexer, 'input: 'lexer>(
    _lexer: &'lexer dyn NonStreamingLexer<'input, DefaultLexerTypes>,
    indent: usize,
    content: TextList<'input>,
) -> ListItem<'input> {
    ListItem::new(indent, content)
}
pub fn generate_checkable_list_item<'lexer, 'input: 'lexer>(
    _lexer: &'lexer dyn NonStreamingLexer<'input, DefaultLexerTypes>,
    indent: usize,
    content: TextList<'input>,
    is_checked: bool,
) -> CheckableListItem<'input> {
    CheckableListItem::new(indent, content, is_checked)
}
pub fn generate_text<'lexer, 'input: 'lexer>(text: TextList<'input>) -> Markdown {
    Markdown::Text { content: text }
}
pub trait Listener {
    fn when(&mut self, item: &Markdown);
}
pub struct ListenerDelegate<'a> {
    listener: &'a mut dyn Listener,
}
impl<'a> ListenerDelegate<'a> {
    pub fn new(listener: &'a mut dyn Listener) -> Self {
        ListenerDelegate { listener }
    }
}
impl<'a> Listener for  ListenerDelegate<'a> {
    fn when(&mut self, item: &Markdown) {
       self.listener.when(item) 
    }
}
pub type TListener<'a> = RefCell<ListenerDelegate<'a>>;
#[cfg(test)]
mod test {
    #[test]
    fn test_markdown() {}
}
